package com.fjzx.androidframe.base.adapter;

import android.support.annotation.NonNull;
import android.support.v7.recyclerview.extensions.AsyncListDiffer;
import android.support.v7.util.DiffUtil;
import android.support.v7.widget.RecyclerView;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.fjzx.androidframe.base.annotation.injector.MultiItemViewInjector;
import com.fjzx.androidframe.base.callback.OnItemClickListener;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 基础多类型item适配器
 *
 * @author xiongyongcong
 */
public abstract class BaseMultiTypeRvAdapter<T> extends RecyclerView.Adapter<BaseMultiTypeRvAdapter.BaseMultiTypeRvHolder> {
    protected LayoutInflater mInflater;
    protected OnItemClickListener listener;
    protected AsyncListDiffer<T> mDiffer;

    public BaseMultiTypeRvAdapter() {
        mDiffer = new AsyncListDiffer(this, createDiffCallback());
    }

    @NonNull
    @Override
    public BaseMultiTypeRvAdapter.BaseMultiTypeRvHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        if (mInflater == null) {
            mInflater = LayoutInflater.from(parent.getContext());
        }
        int[] viewIds = createItemViewIds(parent, viewType);
        return new BaseMultiTypeRvHolder(mInflater.inflate(viewIds[viewType], parent, false));
    }

    protected int[] createItemViewIds(ViewGroup parent, int viewType) {
        return MultiItemViewInjector.inject(this);
    }

    @Override
    public void onBindViewHolder(@NonNull BaseMultiTypeRvAdapter.BaseMultiTypeRvHolder holder, int position) {
        bindData(getItemViewType(position), holder, position, getItem(position));
    }

    @Override
    public int getItemCount() {
        return mDiffer.getCurrentList().size();
    }

    public void setOnItemClickListener(OnItemClickListener listener) {
        this.listener = listener;
    }

    public T getItem(int position) {
        return mDiffer.getCurrentList().get(position);
    }

    public void submitList(List<T> data) {
        mDiffer.submitList(data);
    }

    public List<T> getData() {
        return mDiffer.getCurrentList();
    }

    public void clear() {
        mDiffer.submitList(null);
    }

    @NonNull
    protected abstract DiffUtil.ItemCallback createDiffCallback();

    protected abstract void bindData(int itemViewType, @NonNull BaseMultiTypeRvHolder holder, int position, @NonNull T t);

    public class BaseMultiTypeRvHolder extends RecyclerView.ViewHolder {
        protected Map<Integer, SparseArray<View>> mViewCache = new HashMap<>();

        public BaseMultiTypeRvHolder(View itemView) {
            super(itemView);
            itemView.setOnClickListener(v -> {
                if (listener != null) {
                    listener.onItemClick(v, getLayoutPosition());
                }
            });
        }

        public <T> T getView(int viewType, int id) {
            SparseArray<View> cache = mViewCache.get(viewType);
            if (cache == null) {
                cache = new SparseArray<>();
            }
            View view = cache.get(id);
            if (view == null) {
                view = itemView.findViewById(id);
                cache.put(id, view);
                mViewCache.put(viewType, cache);
            }
            return (T) view;
        }
    }
}
